package sslsockets;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.security.KeyStore;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Enumeration;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import server.ServerResources;

public class SSLSocketServer
{
    public static String hashKeyAlias;
    static String keyStoreFile;
    static String trustKeyStoreFile;
    static private char[] keyStorePassword;
    static private char[] trustKeyStorePassword;
    static String shamirPubFile;
    static String shamirPrivFile;
    static private KeyStore keyStore;
    static private KeyStore trustKeyStore;
    static
    {
        ServerResources resources = new ServerResources();
        keyStoreFile = (String)resources.getObject( "keyStoreFile" );
        trustKeyStoreFile = (String)resources.getObject( "trustKeyStoreFile" );
        keyStorePassword = (char[])resources.getObject( "keyStorePassword" );
        trustKeyStorePassword = (char[])resources.getObject( "trustKeyStorePassword" );
        shamirPrivFile = (String)resources.getObject( "shamirPrivFile" );
        shamirPubFile = (String)resources.getObject( "shamirPubFile" );
        hashKeyAlias = (String)resources.getObject( "hashKeyAlias" );
    }

    public static void main( String[] args ) throws IOException
    {
        try
        {
            TrustManager tm = new X509TrustManager()
            {
                public void checkClientTrusted( X509Certificate[] chain, String authType ) throws CertificateException
                {
                    try
                    {
                        KeyStore ks = KeyStore.getInstance( KeyStore.getDefaultType() );
                        FileInputStream in = new FileInputStream( trustKeyStoreFile );
                        ks.load( in, trustKeyStorePassword );
                        ArrayList<Certificate> trusted = new ArrayList<Certificate>();
                        Enumeration<String> e = ks.aliases();
                        for( ; e.hasMoreElements(); )
                        {
                            trusted.add( ks.getCertificate( e.nextElement() ) );
                        }
                        for( Certificate trustedCert: trusted )
                        {
                            for( Certificate unknownCert: chain )
                            {
                                try
                                {
                                    trustedCert.verify( unknownCert.getPublicKey() );
                                    System.out.println( "Server: Certificates do match!!" );
                                }
                                catch( SignatureException ex2 )
                                {
                                    System.out.println( "Server: Certificates don't match." );
                                }
                            }
                        }
                    }
                    catch( Exception ex )
                    {
                        ex.printStackTrace();
                    }
                }

                public X509Certificate[] getAcceptedIssuers()
                {
                    return null;
                }

                public void checkServerTrusted( X509Certificate[] chain, String authType ) throws CertificateException
                {
                    /* do nothing, you're server */
                }
            };
            KeyStore ks = KeyStore.getInstance( KeyStore.getDefaultType() );
            FileInputStream fin = new FileInputStream( keyStoreFile );
            ks.load( fin, keyStorePassword );
            KeyManagerFactory kmf = KeyManagerFactory.getInstance( "SunX509" );
            kmf.init( ks, keyStorePassword );
            SSLContext ctx = SSLContext.getInstance( "TLS" );
            TrustManager[] tmChain = { tm };
            ctx.init( kmf.getKeyManagers(), tmChain, null );
            SSLServerSocketFactory fac = ctx.getServerSocketFactory();
            SSLServerSocket sslSocket = (SSLServerSocket)fac.createServerSocket( 1234 );
            sslSocket.setNeedClientAuth( false );
            InputStream in;
            ObjectInputStream oin = null;
            Object received;
            OutputStream out;
            ObjectOutputStream oout = null;
            Socket socket = sslSocket.accept();
            in = socket.getInputStream();
            oin = new ObjectInputStream( in );
            out = socket.getOutputStream();
            oout = new ObjectOutputStream( out );
            received = oin.readObject();
            if( received instanceof String )
            {
                System.out.println( "Sever: " + (String)received );
                oout.writeObject( received );
            }
        }
        catch( Exception e )
        {
            e.printStackTrace();
        }
    }
}